package com.sf.ams.biz.impl;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sf.ams.biz.IDataStoreXmlAnalysisBiz;
import com.sf.ams.biz.IUpdateDataBiz;
import com.sf.ams.constant.Constant;
import com.sf.ams.entity.Environment;
import com.sf.ams.entity.Response;
import com.sf.ams.entity.SystemInfo;
import com.sf.ams.entity.enums.ExecuteStatus;
import com.sf.ams.exception.AmsException;
import com.sf.ams.utils.AESUtil;
import com.sf.ams.utils.StringUtil;
import com.sf.ams.utils.XMLWriterUtil;


/**
 * 描述：
 * 
 * <pre>HISTORY
 * ****************************************************************************
 *  ID   DATE           PERSON          REASON
 *  1    2017年10月10日      Simba.Hua         Create
 * ****************************************************************************
 * </pre>
 * @author Simba.Hua
 */
@Service("updateDataBiz")
public class UpdateDataBizImpl implements IUpdateDataBiz {
	@Autowired
	private IDataStoreXmlAnalysisBiz dataStoreXmlAnalysisBiz;
	private static final String SYSTEM_CANNOT_NULL = "系统不能为空！";
	private static final String SYSTEM_CODE_PATH = "/automaticSql/systems/system[systemCode='";
	private Logger logger  = LoggerFactory.getLogger(getClass());
	@Override
	public Response updateEnvironment(SystemInfo system) {
		SystemInfo trueSystem = dataStoreXmlAnalysisBiz.getSystemBySystemCode(system.getSystemCode(),true);
		if(trueSystem == null)return new Response(Response.STATUS_FAIL, "", -1);
		List<Environment> environments = system.getEnvironments();
		List<Environment> addEnvironments = new ArrayList<>();
		environments.forEach(e -> {
			if(e.getEnvironmentIndex() != null) {
				XMLWriterUtil.getInstance().updateXml(updateNodePath(system.getSystemCode(),e.getEnvironmentIndex()), updateElement(e,system.getSystemCode()));
			} else {
				addEnvironments.add(e);
			}
		});
		boolean flag = true;
		if (!addEnvironments.isEmpty()) {
			flag = XMLWriterUtil.getInstance().addElements(SYSTEM_CODE_PATH + system.getSystemCode(), 
											addEnvironments(addEnvironments,trueSystem.getMaxIndex(),trueSystem.getSystemCode()),
											trueSystem.getMaxIndex().intValue() + addEnvironments.size());
		}
		return new Response(flag ? Response.STATUS_SUCCESS : Response.STATUS_FAIL, "", -1);
	}
	private String updateNodePath(String systemCode,Integer environmentIndex) {
		StringBuilder result = new StringBuilder();
		result.append(SYSTEM_CODE_PATH)
		  .append(systemCode)
		  .append("']/environments/environment[environmentIndex='")
		  .append(environmentIndex)
		  .append("']");
		return result.toString();
	}
	/**
	 * 更新环境
	 * @param environment
	 * @return
	 */
	private Map<String,String> updateElement(Environment environment,String systemCode) {
		Map<String,String> result = new HashMap<>();
		result.put("environmentType", environment.getEnvironmentType());
		result.put("dataBaseType", environment.getDataBaseType());
		result.put("dataBaseConnection", environment.getDataBaseConnection());
		result.put("dataBaseUserName", environment.getDataBaseUserName());
		if(StringUtil.isEmpty(environment.getDataBasePassword())){
			throw new AmsException("数据库密码不能为空!");
		}
		if(!Constant.PASSWORD_FLAG.equals(environment.getDataBasePassword())){
			result.put("dataBasePassword", AESUtil.AESEncode(systemCode, environment.getDataBasePassword()));
		}
		result.put("currentIndex", environment.getCurrentIndex()== null?"1":environment.getCurrentIndex().toString());
		return result;
	}
	/**
	 * 新增环境Environment
	 * @param environments
	 * @param maxIndex
	 * @return
	 */
	private List<Map<String,String>> addEnvironments(List<Environment> environments,Integer maxIndex,String systemCode) {
		List<Map<String,String>> result = new ArrayList<>();
		Integer currentIndex = maxIndex;
		for(Environment e : environments) {
			currentIndex ++;
			Map<String,String> environment = updateElement(e,systemCode);
			environment.put("environmentIndex",String.valueOf(currentIndex));
			environment.put("lastExecuteTime", "");
			environment.put("currentStatus", ExecuteStatus.INIT.toString());
			environment.put("executeFailReason", "");
			result.add(environment);
		}
		return result;
	}
	@Override
	public Response saveSystem(SystemInfo system) {
		uploadFile(system);
		return XMLWriterUtil.getInstance().addSystem(system)?new Response(Response.STATUS_SUCCESS,"",-1):new Response(Response.STATUS_FAIL,"",-1);
	}
	@Override
	public Response editSystem(SystemInfo system) {
		uploadFile(system);
		return XMLWriterUtil.getInstance().updateXml(SYSTEM_CODE_PATH+system.getSystemCode()+"']", editSystemElement(system))?
				new Response(Response.STATUS_SUCCESS,"",-1):new Response(Response.STATUS_FAIL,"",-1);
	}
	private Map<String,String> editSystemElement(SystemInfo system){
		Map<String,String> elements = new HashMap<>();
		elements.put("pathType", system.getPathType());
		elements.put("pathAddress", system.getPathAddress());
		elements.put("gitUserName", system.getGitUserName());
		if(!Constant.PASSWORD_FLAG.equals(system.getGitPassword())){
			elements.put("gitPassword", AESUtil.AESEncode(system.getSystemCode(), system.getGitPassword()));
		}
		elements.put("gitBranch", system.getGitBranch());
		elements.put("sqlPath", system.getSqlPath());
		return elements;
	}
	private void uploadFile(SystemInfo system) {
		if(system == null) throw new AmsException(SYSTEM_CANNOT_NULL);
		if ("file".equals(system.getPathType())) {
			//核对文件类型
			checkFileType(system.getFilePathAddress().getOriginalFilename());
			
			system.setPathAddress(system.getFilePathAddress().getOriginalFilename());
			BufferedOutputStream output = null;
			FileOutputStream fileOutput = null;
			String uploadFilePath = Constant.LOCAL_CODE_DIR + Constant.PATH_SPLIT_CHARACTOR + 
					system.getSystemCode() + Constant.PATH_SPLIT_CHARACTOR + 
					Constant.FILE_SQL_PATH ;
			try {
				//上次文件的基础路径
				File uploadParentFile = new File(uploadFilePath);
				
				if (uploadParentFile.exists()) {
					deleteDirFile(uploadParentFile);
				}
				uploadParentFile.mkdirs();
				File uploadFile = new File(uploadFilePath + Constant.PATH_SPLIT_CHARACTOR +
						system.getFilePathAddress().getOriginalFilename());
				fileOutput = new FileOutputStream(uploadFile);
				output = new BufferedOutputStream(fileOutput);
				output.write(system.getFilePathAddress().getBytes());
				output.flush();
			} catch (IOException e) {
				logger.error("上传文件失败",e);
			} finally {
				if(output != null){
					try {
						output.close();
					} catch (IOException e) {
						logger.error("关闭数据流失败",e);
					}	
				}
				if (fileOutput != null) {
					try {
						fileOutput.close();
					} catch (IOException e) {
						logger.error("关闭数据流失败",e);
					}
				}
					
			}
		}
	}
	/**
	 * 循环删除file下的目录及文件
	 * @param dir
	 * @return
	 */
	private boolean deleteDirFile(File dir){
		if(dir.isDirectory()){
			List<String> children = Arrays.asList(dir.list());
			for(String f : children) {
				if(!deleteDirFile(new File(dir,f))) {//循环删除子文件
					return false;
				}
			}
		}
		return dir.delete();
	}
	private void checkFileType(String fileName) {
		if(!fileName.toLowerCase().endsWith(".zip") && !fileName.toLowerCase().endsWith(".rar")) {
			throw new AmsException("上传文件必须是zip或rar文件");
		}
	}
	@Override
	public Response deleteEnvironment(SystemInfo system) {
		if (system == null) throw new AmsException(SYSTEM_CANNOT_NULL);
		String parentElement = SYSTEM_CODE_PATH+system.getSystemCode()+"']/environments";
		List<Environment> environments = system.getEnvironments();
		List<String> environmentTypes = new ArrayList<>();
		environments.forEach(e -> environmentTypes.add("/environment[environmentType = '" + e.getEnvironmentType() + "']")
		);
		return XMLWriterUtil.getInstance().deleteElement(parentElement, environmentTypes)?new Response(Response.STATUS_SUCCESS,"",-1):new Response(Response.STATUS_FAIL,"",-1);
	}
	@Override
	public Response deleteSystem(String systemCode) {
		if (StringUtil.isEmpty(systemCode)) {
			throw new AmsException(SYSTEM_CANNOT_NULL);	
		}
		String parentElement = "/automaticSql/systems";
		List<String> systemCodes = new ArrayList<>();
		systemCodes.add( "/system[systemCode='" + systemCode + "']");
	  return XMLWriterUtil.getInstance().deleteElement(parentElement, systemCodes)?new Response(Response.STATUS_SUCCESS,"",-1):new Response(Response.STATUS_FAIL,"",-1);
	}

}
